#include <math.h>
#include <stdio.h>

#define U_INT16 unsigned short

short display_debug;
short display_as_real;

#define TRUE  1
#define FALSE 0

  /*******************************/
  /*  Generic Unit Conversion    */
  /*******************************/

#define DCM2_TO_PSI   1.450377e-5

#define T_NTP         298.15
#define T_STP         273.15


#include "ps_def.h"


typedef struct 
        {
           char     name[20];/* C string with sensor name */
           float    offset;  /* volts at 0 PSI */
           float    span;    /* volts at full scale - volts at 0 psi */
           float    range;   /* PSIG at full scale */
           float    dcm2_per_iu;
        } PS_CALIB;


#define NUM_SENSORS 4

PS_CALIB ps_calib[NUM_SENSORS] = {
                 { "PSI_15",  PSI_15_OFFSET,  PSI_15_SPAN,  PSI_15_RANGE,  PSI_15_DCM2_PER_IU  },
                 { "PSI_100", PSI_100_OFFSET, PSI_100_SPAN, PSI_100_RANGE, PSI_100_DCM2_PER_IU },
                 { "PSI_200", PSI_200_OFFSET, PSI_200_SPAN, PSI_200_RANGE, PSI_200_DCM2_PER_IU },
                 { "PSI_300", PSI_300_OFFSET, PSI_300_SPAN, PSI_300_RANGE, PSI_300_DCM2_PER_IU }
             };




short pressure_to_digital ( unsigned short pressure,
                                     float offset,
                                     float span,
                                     float range,
                                     float dcm2_per_iu )

{

    float sensor;
    float adc_in;
    float adc_out;
    short digital;


    if (display_debug) printf ( "Pres: 0x%-6hx  ", pressure );

       /* the pressure, sensor voltage relationship */
            /* volts */         /* volts/psi */
    sensor = offset + (float)pressure * (span/range);

    if (display_debug) printf ( "Sensor: %4.2f  ", sensor );

    digital = sensor * 16384;
    if (sensor >= 4.0) digital = 0xffff;

    if (display_debug) printf ( "digital : 0x%-6hx\n", digital );

    return digital;
}

   

void print_pressures_to_digital( char *gas,
                            float offset,
                            float span,
                            float range,
                            float dcm2_per_iu )
{

    short i;
    unsigned short pressure;
    short digital;

   printf ( "\f\n#define %s_DCM2_PER_IU   %d\n\n", gas, (int)dcm2_per_iu );

    printf ( "\nconst U_INT16 %s_Pres_To_ADC[] = {", gas );

    for (i= 0 ; i<256 ; i++ )
    {
        pressure = i*256;

        if (pressure > range)
        {
            break;
        }
        else
        {
            digital = pressure_to_digital(pressure ,offset,span,range,dcm2_per_iu );
        }

        if (display_debug != TRUE )
        {
            if ((i%8)==0)
            {
               if (display_as_real)
	          printf ( "\n/*%6.2f */  %6.2f,", (float)pressure*dcm2_per_iu*DCM2_TO_PSI, (float)digital/10922.0 );
               else
	          printf ( "\n/*%6hx */  0x%-6hx,", pressure, digital );
            }
            else
            {
               if (display_as_real)
	          printf ( " %6.2f,", (float)digital/10922.0 );
               else
	          printf ( " 0x%-6hx,", digital );
            }
       }
    }

    pressure = i*256-1;
    if (pressure > range)
    {
       digital = pressure_to_digital(range      ,offset,span,range,dcm2_per_iu );
    }
    else
    {
       digital = pressure_to_digital(pressure ,offset,span,range,dcm2_per_iu );
    }

    if (display_debug != TRUE )
    {
        if (display_as_real)
           printf ( " %6.2f };\n", (float)digital/10922.0 );
        else
           printf ( " 0x%-6hx };\n", digital );
    }

}



unsigned short digital_to_pressure ( unsigned short digital,
                         float offset,
                         float span,
                         float range,
                         float dcm2_per_iu )
{
    float adc_out;
    float adc_in;
    float sensor;
    float pressure;

    if (display_debug) printf ( "Digital: %-6hx  ", digital );

    sensor = ((float)digital/16384.0);

    if (display_debug) printf ( "sensor: %4.2f  ", sensor );

    /*       0----+----1----+----2----+----3----+----4----+----5 */
    /*         ^----------------- s p a n ---------------^       */
    /*         0 psi <----- range ---------------------->100 psi */
    /*                range/span = psi/per volt                 */

    pressure = (sensor - offset) * (range/span);

    if (pressure < 0 ) pressure = 0;
    if (pressure > range) pressure = range;

    if (display_debug) printf ( "Pres: 0x%-6hx\n", (short)pressure );

    return (short)pressure;

}


void print_digital_to_pressures ( char *gas,
                            float offset,
                            float span,
                            float range,
                            float dcm2_per_iu )
{

    short i;
    unsigned short digital;
    unsigned short pressure;

    
    printf ( "\f\nconst U_INT16 %s_ADC_To_Pres[] = {           ", gas );
   
    for (i= 0 ; i<256 ; i++) 
    {
        digital =  i*256;
        pressure    = digital_to_pressure(digital ,offset,span,range,dcm2_per_iu );

        if (display_debug != TRUE )
        {
            if ((i%8)==0)
            {
               if (display_as_real)
                   printf ( "\n/*%6.2f */  %6.2f,", (float)digital/10922.0, (float)pressure*dcm2_per_iu*DCM2_TO_PSI );
               else
                   printf ( "\n/*%5hx */  0x%-6lx,", digital, (unsigned short)pressure );
            }
            else
            {
               if (display_as_real)
	           printf ( " %6.2f,", (float)pressure*dcm2_per_iu*DCM2_TO_PSI );
               else
	           printf ( " 0x%-6hx,",pressure );
            }
       }

    }

    digital = i*256-1;
    pressure    = digital_to_pressure(digital ,offset,span,range,dcm2_per_iu );

    if (display_debug != TRUE )
    {
        if (display_as_real)
           printf ( " %6.2f };\n", (float)pressure*dcm2_per_iu*DCM2_TO_PSI );
        else
           printf ( " 0x%-6hx };\n",pressure );
    }

}


int main(int argc, char *argv[] )
{
  short index;

   display_as_real = FALSE;
   display_debug   = FALSE;

   if ( argc >= 1 )
   {
      if ( strcmp( "-r", argv[1] ) == 0 )  display_as_real = TRUE;
      if ( strcmp( "-d", argv[1] ) == 0 )  display_debug   = TRUE;
   }

  for ( index = 0 ; index < NUM_SENSORS ; index++ )
  {
     print_pressures_to_digital ( ps_calib[index].name,
                          ps_calib[index].offset, 
                          ps_calib[index].span, 
                          ps_calib[index].range,
                          ps_calib[index].dcm2_per_iu );

     print_digital_to_pressures ( ps_calib[index].name,
                          ps_calib[index].offset, 
                          ps_calib[index].span, 
                          ps_calib[index].range,
                          ps_calib[index].dcm2_per_iu );

  }

  return 0;

}

